String pattern matcher in 6502 assembly.
By Paul Guertin (pg@sff.net), 30 August 2000.
This routine matches a string against a pattern and returns with the carry bit set if they match, or clear if they don't. The two characters ? and * have a special meaning when they appear in the pattern. All other characters match themselves.

? matches any one character. For example, F?? matches FOO but not FU, and ?? matches all two-character strings.

* matches any string, including the empty string. For example, F* matches all strings starting with F. *O*O* matches all strings with at least two Os. Finally, ?* matches all non-empty strings.

Both the pattern and the string must be NUL-terminated (that it, followed with a 00 byte) and at most 255 characters long (excluding the NUL).

; Input:  A NUL-terminated, <255-length pattern at address PATTERN.
;         A NUL-terminated, <255-length string pointed to by STR.
;
; Output: Carry bit = 1 if the string matches the pattern, = 0 if not.
;
; Notes:  Clobbers A, X, Y. Each * in the pattern uses 4 bytes of stack.
;

MATCH1  EQU "?"         ; Matches exactly 1 character
MATCHN  EQU "*"         ; Matches any string (including "")
PATTERN EQU $2000       ; Address of pattern
STR     EQU $6          ; Pointer to string to match

PATTERNMATCH:
        LDX #$00        ; X is an index in the pattern
        LDY #$FF        ; Y is an index in the string
NEXT    LDA PATTERN,X   ; Look at next pattern character
        CMP #MATCHN     ; Is it a star?
        BEQ STAR        ; Yes, do the complicated stuff
        INY             ; No, let's look at the string
        CMP #MATCH1     ; Is the pattern caracter a ques?
        BNE REG         ; No, it's a regular character
        LDA (STR),Y     ; Yes, so it will match anything
        BEQ FAIL        ;  except the end of string
REG     CMP (STR),Y     ; Are both characters the same?
        BNE FAIL        ; No, so no match
        INX             ; Yes, keep checking
        CMP #0          ; Are we at end of string?
        BNE NEXT        ; Not yet, loop
FOUND   RTS             ; Success, return with C=1

STAR    INX             ; Skip star in pattern
        CMP PATTERN,X   ; String of stars equals one star
        BEQ STAR        ;  so skip them also
STLOOP  TXA             ; We first try to match with * = ""
        PHA             ;  and grow it by 1 character every
        TYA             ;  time we loop
        PHA             ; Save X and Y on stack
        JSR NEXT        ; Recursive call
        PLA             ; Restore X and Y
        TAY
        PLA
        TAX
        BCS FOUND       ; We found a match, return with C=1
        INY             ; No match yet, try to grow * string
        LDA (STR),Y     ; Are we at the end of string?
        BNE STLOOP      ; Not yet, add a character
FAIL    CLC             ; Yes, no match found, return with C=0
        RTS
Last page update: September 8, 2000.